// ignore_for_file: non_constant_identifier_names
// ignore_for_file: camel_case_types
// ignore_for_file: prefer_single_quotes

import 'package:mziot/app/data/add_device_entity.dart';
import 'package:mziot/app/data/circle_detail_entity.dart';
import 'package:mziot/app/data/circle_list_entity.dart';
import 'package:mziot/app/data/cmd_entity.dart';
import 'package:mziot/app/data/comment_list_entity.dart';
import 'package:mziot/app/data/device_group_entity.dart';
import 'package:mziot/app/data/device_info_entity.dart';
import 'package:mziot/app/data/device_list_entity.dart';
import 'package:mziot/app/data/group_down_entity.dart';
import 'package:mziot/app/data/group_info_entity.dart';
import 'package:mziot/app/data/product_group_entity.dart';
import 'package:mziot/app/data/profile_entity.dart';
import 'package:mziot/app/data/scene_info_entity.dart';
import 'package:mziot/app/data/scene_list_entity.dart';
import 'package:mziot/app/data/scene_params_entity.dart';
import 'package:mziot/app/data/user_entity.dart';

JsonConvert jsonConvert = JsonConvert();

class JsonConvert {
  T? convert<T>(dynamic value) {
    if (value == null) {
      return null;
    }
    return asT<T>(value);
  }

  List<T?>? convertList<T>(List<dynamic>? value) {
    if (value == null) {
      return null;
    }
    try {
      return value.map((dynamic e) => asT<T>(e)).toList();
    } catch (e, stackTrace) {
      print('asT<$T> $e $stackTrace');
      return <T>[];
    }
  }

  List<T>? convertListNotNull<T>(dynamic value) {
    if (value == null) {
      return null;
    }
    try {
      return (value as List<dynamic>).map((dynamic e) => asT<T>(e)!).toList();
    } catch (e, stackTrace) {
      print('asT<$T> $e $stackTrace');
      return <T>[];
    }
  }

  T? asT<T extends Object?>(dynamic value) {
    if (value is T) {
      return value;
    }
    final String type = T.toString();
    try {
      final String valueS = value.toString();
      if (type == "String") {
        return valueS as T;
      } else if (type == "int") {
        final int? intValue = int.tryParse(valueS);
        if (intValue == null) {
          return double.tryParse(valueS)?.toInt() as T?;
        } else {
          return intValue as T;
        }
      } else if (type == "double") {
        return double.parse(valueS) as T;
      } else if (type == "DateTime") {
        return DateTime.parse(valueS) as T;
      } else if (type == "bool") {
        if (valueS == '0' || valueS == '1') {
          return (valueS == '1') as T;
        }
        return (valueS == 'true') as T;
      } else {
        return JsonConvert.fromJsonAsT<T>(value);
      }
    } catch (e, stackTrace) {
      print('asT<$T> $e $stackTrace');
      return null;
    }
  }

  //Go back to a single instance by type
  static M? _fromJsonSingle<M>(Map<String, dynamic> json) {
    final String type = M.toString();
    if (type == (AddDeviceEntity).toString()) {
      return AddDeviceEntity.fromJson(json) as M;
    }
    if (type == (CmdEntity).toString()) {
      return CmdEntity.fromJson(json) as M;
    }
    if (type == (DeviceGroupEntity).toString()) {
      return DeviceGroupEntity.fromJson(json) as M;
    }
    if (type == (DeviceGroupList).toString()) {
      return DeviceGroupList.fromJson(json) as M;
    }
    if (type == (DeviceInfoEntity).toString()) {
      return DeviceInfoEntity.fromJson(json) as M;
    }
    if (type == (DeviceListEntity).toString()) {
      return DeviceListEntity.fromJson(json) as M;
    }
    if (type == (DeviceListList).toString()) {
      return DeviceListList.fromJson(json) as M;
    }
    if (type == (GroupDownEntity).toString()) {
      return GroupDownEntity.fromJson(json) as M;
    }
    if (type == (GroupInfoEntity).toString()) {
      return GroupInfoEntity.fromJson(json) as M;
    }
    if (type == (ProductGroupEntity).toString()) {
      return ProductGroupEntity.fromJson(json) as M;
    }
    if (type == (ProductGroupProductVos).toString()) {
      return ProductGroupProductVos.fromJson(json) as M;
    }
    if (type == (SceneInfoEntity).toString()) {
      return SceneInfoEntity.fromJson(json) as M;
    }
    if (type == (SceneInfoMomentVo).toString()) {
      return SceneInfoMomentVo.fromJson(json) as M;
    }
    if (type == (SceneListEntity).toString()) {
      return SceneListEntity.fromJson(json) as M;
    }
    if (type == (SceneParamsEntity).toString()) {
      return SceneParamsEntity.fromJson(json) as M;
    }
    if (type == (SceneParamsLightOffs).toString()) {
      return SceneParamsLightOffs.fromJson(json) as M;
    }
    if (type == (UserEntity).toString()) {
      return UserEntity.fromJson(json) as M;
    }

    if (type == (CircleListEntity).toString()) {
      return CircleListEntity.fromJson(json) as M;
    }
    if (type == (CircleListVos).toString()) {
      return CircleListVos.fromJson(json) as M;
    }
    if (type == (CircleListVosList).toString()) {
      return CircleListVosList.fromJson(json) as M;
    }
    if (type == (ProfileEntity).toString()) {
      return ProfileEntity.fromJson(json) as M;
    }
    if (type == (CircleDetailEntity).toString()) {
      return CircleDetailEntity.fromJson(json) as M;
    }
    if (type == (CommentListEntity).toString()) {
      return CommentListEntity.fromJson(json) as M;
    }
    if (type == (CommentListList).toString()) {
      return CommentListList.fromJson(json) as M;
    }

    print("$type not found");

    return null;
  }

  //list is returned by type
  static M? _getListChildType<M>(List<dynamic> data) {
    if (<AddDeviceEntity>[] is M) {
      return data.map<AddDeviceEntity>((dynamic e) => AddDeviceEntity.fromJson(e)).toList() as M;
    }
    if (<CmdEntity>[] is M) {
      return data.map<CmdEntity>((dynamic e) => CmdEntity.fromJson(e)).toList() as M;
    }
    if (<DeviceGroupEntity>[] is M) {
      return data.map<DeviceGroupEntity>((dynamic e) => DeviceGroupEntity.fromJson(e)).toList()
          as M;
    }
    if (<DeviceGroupList>[] is M) {
      return data.map<DeviceGroupList>((dynamic e) => DeviceGroupList.fromJson(e)).toList() as M;
    }
    if (<DeviceInfoEntity>[] is M) {
      return data.map<DeviceInfoEntity>((dynamic e) => DeviceInfoEntity.fromJson(e)).toList() as M;
    }
    if (<DeviceListEntity>[] is M) {
      return data.map<DeviceListEntity>((dynamic e) => DeviceListEntity.fromJson(e)).toList() as M;
    }
    if (<DeviceListList>[] is M) {
      return data.map<DeviceListList>((dynamic e) => DeviceListList.fromJson(e)).toList() as M;
    }
    if (<GroupDownEntity>[] is M) {
      return data.map<GroupDownEntity>((dynamic e) => GroupDownEntity.fromJson(e)).toList() as M;
    }
    if (<GroupInfoEntity>[] is M) {
      return data.map<GroupInfoEntity>((dynamic e) => GroupInfoEntity.fromJson(e)).toList() as M;
    }
    if (<ProductGroupEntity>[] is M) {
      return data.map<ProductGroupEntity>((dynamic e) => ProductGroupEntity.fromJson(e)).toList()
          as M;
    }
    if (<ProductGroupProductVos>[] is M) {
      return data
          .map<ProductGroupProductVos>((dynamic e) => ProductGroupProductVos.fromJson(e))
          .toList() as M;
    }
    if (<SceneInfoEntity>[] is M) {
      return data.map<SceneInfoEntity>((dynamic e) => SceneInfoEntity.fromJson(e)).toList() as M;
    }
    if (<SceneInfoMomentVo>[] is M) {
      return data.map<SceneInfoMomentVo>((dynamic e) => SceneInfoMomentVo.fromJson(e)).toList()
          as M;
    }
    if (<SceneListEntity>[] is M) {
      return data.map<SceneListEntity>((dynamic e) => SceneListEntity.fromJson(e)).toList() as M;
    }
    if (<SceneParamsEntity>[] is M) {
      return data.map<SceneParamsEntity>((dynamic e) => SceneParamsEntity.fromJson(e)).toList()
          as M;
    }
    if (<SceneParamsLightOffs>[] is M) {
      return data
          .map<SceneParamsLightOffs>((dynamic e) => SceneParamsLightOffs.fromJson(e))
          .toList() as M;
    }
    if (<UserEntity>[] is M) {
      return data.map<UserEntity>((dynamic e) => UserEntity.fromJson(e)).toList() as M;
    }
    if (<CircleListEntity>[] is M) {
      return data.map<CircleListEntity>((dynamic e) => CircleListEntity.fromJson(e)).toList() as M;
    }
    if (<CircleListEntity>[] is M) {
      return data.map<CircleListEntity>((e) => CircleListEntity.fromJson(e)).toList() as M;
    }
    if (<CircleListVos>[] is M) {
      return data.map<CircleListVos>((e) => CircleListVos.fromJson(e)).toList() as M;
    }
    if (<CircleListVosList>[] is M) {
      return data.map<CircleListVosList>((e) => CircleListVosList.fromJson(e)).toList() as M;
    }
    if (<ProfileEntity>[] is M) {
      return data.map<ProfileEntity>((dynamic e) => ProfileEntity.fromJson(e)).toList() as M;
    }
    if (<CircleDetailEntity>[] is M) {
      return data.map<CircleDetailEntity>((dynamic e) => CircleDetailEntity.fromJson(e)).toList()
          as M;
    }
    if (<CommentListEntity>[] is M) {
      return data.map<CommentListEntity>((dynamic e) => CommentListEntity.fromJson(e)).toList()
          as M;
    }
    if (<CommentListList>[] is M) {
      return data.map<CommentListList>((dynamic e) => CommentListList.fromJson(e)).toList() as M;
    }

    print("${M.toString()} not found");

    return null;
  }

  static M? fromJsonAsT<M>(dynamic json) {
    if (json == null) {
      return null;
    }
    if (json is List) {
      return _getListChildType<M>(json);
    } else {
      return _fromJsonSingle<M>(json as Map<String, dynamic>);
    }
  }
}
